"""
进度监控系统

实现实时进度显示、ETA计算、速度统计等功能。
"""

import time
import threading
from typing import Dict, List, Optional, Any, Callable
from dataclasses import dataclass, field
from datetime import datetime, timezone, timedelta

from ..utils.logger import get_module_logger

logger = get_module_logger(__name__)


@dataclass
class ProgressSnapshot:
    """进度快照"""
    timestamp: datetime
    current: int
    total: int
    rate: float
    eta_seconds: Optional[float] = None
    custom_metrics: Dict[str, Any] = field(default_factory=dict)


class ProgressTracker:
    """进度跟踪器
    
    跟踪单个任务的进度信息。
    """
    
    def __init__(self, task_id: str, total: int, description: str = ""):
        """初始化进度跟踪器
        
        Args:
            task_id: 任务ID
            total: 总工作量
            description: 任务描述
        """
        self.task_id = task_id
        self.total = total
        self.description = description
        self.current = 0
        self.start_time = time.time()
        self.last_update_time = self.start_time
        self.snapshots: List[ProgressSnapshot] = []
        self.custom_metrics: Dict[str, Any] = {}
        self._lock = threading.Lock()
        
        logger.debug(f"创建进度跟踪器: {task_id}, 总量: {total}")
    
    def update(self, current: int, custom_metrics: Optional[Dict[str, Any]] = None):
        """更新进度
        
        Args:
            current: 当前进度
            custom_metrics: 自定义指标
        """
        with self._lock:
            self.current = min(current, self.total)
            self.last_update_time = time.time()
            
            if custom_metrics:
                self.custom_metrics.update(custom_metrics)
            
            # 创建快照
            snapshot = self._create_snapshot()
            self.snapshots.append(snapshot)
            
            # 保持最近100个快照
            if len(self.snapshots) > 100:
                self.snapshots = self.snapshots[-100:]
    
    def increment(self, delta: int = 1, custom_metrics: Optional[Dict[str, Any]] = None):
        """增量更新进度
        
        Args:
            delta: 增量
            custom_metrics: 自定义指标
        """
        self.update(self.current + delta, custom_metrics)
    
    def get_progress_info(self) -> Dict[str, Any]:
        """获取进度信息
        
        Returns:
            进度信息字典
        """
        with self._lock:
            elapsed = time.time() - self.start_time
            rate = self.current / elapsed if elapsed > 0 else 0
            
            # 计算ETA
            eta_seconds = None
            if rate > 0 and self.current < self.total:
                remaining = self.total - self.current
                eta_seconds = remaining / rate
            
            return {
                'task_id': self.task_id,
                'description': self.description,
                'current': self.current,
                'total': self.total,
                'percentage': (self.current / self.total * 100) if self.total > 0 else 0,
                'elapsed_seconds': elapsed,
                'rate': rate,
                'eta_seconds': eta_seconds,
                'custom_metrics': self.custom_metrics.copy(),
                'is_complete': self.current >= self.total
            }
    
    def get_rate_history(self, window_seconds: int = 60) -> List[float]:
        """获取速率历史
        
        Args:
            window_seconds: 时间窗口（秒）
            
        Returns:
            速率历史列表
        """
        with self._lock:
            cutoff_time = datetime.now(timezone.utc) - timedelta(seconds=window_seconds)
            recent_snapshots = [
                s for s in self.snapshots 
                if s.timestamp >= cutoff_time
            ]
            return [s.rate for s in recent_snapshots]
    
    def _create_snapshot(self) -> ProgressSnapshot:
        """创建进度快照"""
        elapsed = time.time() - self.start_time
        rate = self.current / elapsed if elapsed > 0 else 0
        
        # 计算ETA
        eta_seconds = None
        if rate > 0 and self.current < self.total:
            remaining = self.total - self.current
            eta_seconds = remaining / rate
        
        return ProgressSnapshot(
            timestamp=datetime.now(timezone.utc),
            current=self.current,
            total=self.total,
            rate=rate,
            eta_seconds=eta_seconds,
            custom_metrics=self.custom_metrics.copy()
        )


class ProgressMonitor:
    """进度监控器
    
    管理多个进度跟踪器，提供统一的监控接口。
    """
    
    def __init__(self):
        """初始化进度监控器"""
        self.trackers: Dict[str, ProgressTracker] = {}
        self.callbacks: List[Callable[[Dict[str, Any]], None]] = []
        self._lock = threading.Lock()
        self._monitor_thread = None
        self._stop_monitoring = False
        
        logger.info("进度监控器初始化完成")
    
    def create_tracker(self, task_id: str, total: int, description: str = "") -> ProgressTracker:
        """创建进度跟踪器
        
        Args:
            task_id: 任务ID
            total: 总工作量
            description: 任务描述
            
        Returns:
            进度跟踪器
        """
        with self._lock:
            tracker = ProgressTracker(task_id, total, description)
            self.trackers[task_id] = tracker
            
            logger.info(f"创建进度跟踪器: {task_id}")
            return tracker
    
    def remove_tracker(self, task_id: str):
        """移除进度跟踪器
        
        Args:
            task_id: 任务ID
        """
        with self._lock:
            if task_id in self.trackers:
                del self.trackers[task_id]
                logger.info(f"移除进度跟踪器: {task_id}")
    
    def get_tracker(self, task_id: str) -> Optional[ProgressTracker]:
        """获取进度跟踪器
        
        Args:
            task_id: 任务ID
            
        Returns:
            进度跟踪器或None
        """
        with self._lock:
            return self.trackers.get(task_id)
    
    def get_all_progress(self) -> Dict[str, Dict[str, Any]]:
        """获取所有任务的进度信息
        
        Returns:
            所有任务的进度信息
        """
        with self._lock:
            return {
                task_id: tracker.get_progress_info()
                for task_id, tracker in self.trackers.items()
            }
    
    def get_summary(self) -> Dict[str, Any]:
        """获取进度摘要
        
        Returns:
            进度摘要信息
        """
        with self._lock:
            total_tasks = len(self.trackers)
            completed_tasks = sum(1 for t in self.trackers.values() if t.current >= t.total)
            
            # 计算总体进度
            total_work = sum(t.total for t in self.trackers.values())
            completed_work = sum(t.current for t in self.trackers.values())
            overall_percentage = (completed_work / total_work * 100) if total_work > 0 else 0
            
            # 计算平均速率
            rates = [t.get_progress_info()['rate'] for t in self.trackers.values()]
            avg_rate = sum(rates) / len(rates) if rates else 0
            
            return {
                'total_tasks': total_tasks,
                'completed_tasks': completed_tasks,
                'running_tasks': total_tasks - completed_tasks,
                'overall_percentage': overall_percentage,
                'total_work': total_work,
                'completed_work': completed_work,
                'average_rate': avg_rate
            }
    
    def add_callback(self, callback: Callable[[Dict[str, Any]], None]):
        """添加进度回调函数
        
        Args:
            callback: 回调函数
        """
        self.callbacks.append(callback)
    
    def remove_callback(self, callback: Callable[[Dict[str, Any]], None]):
        """移除进度回调函数
        
        Args:
            callback: 回调函数
        """
        if callback in self.callbacks:
            self.callbacks.remove(callback)
    
    def start_monitoring(self, interval: float = 1.0):
        """开始监控
        
        Args:
            interval: 监控间隔（秒）
        """
        if self._monitor_thread and self._monitor_thread.is_alive():
            return
        
        self._stop_monitoring = False
        self._monitor_thread = threading.Thread(
            target=self._monitor_loop,
            args=(interval,),
            daemon=True
        )
        self._monitor_thread.start()
        
        logger.info("开始进度监控")
    
    def stop_monitoring(self):
        """停止监控"""
        self._stop_monitoring = True
        if self._monitor_thread:
            self._monitor_thread.join(timeout=5.0)
        
        logger.info("停止进度监控")
    
    def _monitor_loop(self, interval: float):
        """监控循环"""
        while not self._stop_monitoring:
            try:
                # 获取所有进度信息
                all_progress = self.get_all_progress()
                summary = self.get_summary()
                
                # 调用回调函数
                for callback in self.callbacks:
                    try:
                        callback({
                            'progress': all_progress,
                            'summary': summary,
                            'timestamp': datetime.now(timezone.utc).isoformat()
                        })
                    except Exception as e:
                        logger.warning(f"进度回调函数执行失败: {e}")
                
                time.sleep(interval)
                
            except Exception as e:
                logger.error(f"监控循环出错: {e}")
                time.sleep(interval)
    
    def cleanup_completed_tasks(self):
        """清理已完成的任务"""
        with self._lock:
            completed_tasks = [
                task_id for task_id, tracker in self.trackers.items()
                if tracker.current >= tracker.total
            ]
            
            for task_id in completed_tasks:
                del self.trackers[task_id]
            
            if completed_tasks:
                logger.info(f"清理了 {len(completed_tasks)} 个已完成的任务")
    
    def __enter__(self):
        """上下文管理器入口"""
        self.start_monitoring()
        return self
    
    def __exit__(self, exc_type, exc_val, exc_tb):
        """上下文管理器出口"""
        self.stop_monitoring()
